<?php

namespace Plu\qdh\Services;

use Httpful\Request;
use Plu\qdh\Services\ServiceBase;
use Plu\qdh\Services\OrderService;
use Plu\qdh\Services\ThirdService;
use Plu\qdh\Models\App\Project;
use Plu\qdh\Models\App\Platform;
use Plu\qdh\Models\App\Product;
use Plu\qdh\Models\App\Order;

class PaymentService extends ServiceBase {

    private $_orderId;

    public function setOrderId($orderId) {
        $this->_orderId = $orderId;
    }

    public function initPayment() {
        $orderService = new OrderService;
        $orderInfo    = $orderService->getOrderDetail($this->_orderId);
        $money        = $orderInfo['totalPrice'] * 100;
        $nonce_str    = time().mt_rand(10000, 99999);
        $params = [
            'appid'  => \Wechat::APPID,
            // 商户ID
            'mch_id' => \Wechat::MCH_ID,
            // 随机串，32字符以内
            'nonce_str' => (string) $nonce_str, 
            // 商品名
            'body' => '千岛湖旅游商品', 
            // 订单号，自定义，32字符以内。多次支付时如果重复的话，微信会返回“重复下单”
            'out_trade_no' => $this->_orderId,
            // 订单费用，单位：分
            'total_fee' => $money,
            // IP
            'spbill_create_ip' => $this->request->getClientAddress(),
            // 支付成功后的回调地址
            'notify_url' => 'https://ydpwu.com/order/afterPayment',
            
            'trade_type' => 'JSAPI',
            // 小程序传来的OpenID
            'openid' => $this->passport->getUserId(),
          ];
          
          // 按照要求计算sign 
          $signParams = $this->makeSignParams($params);

          $ch = curl_init();
          $ch = curl_init();
          curl_setopt($ch, CURLOPT_URL, 'https://api.mch.weixin.qq.com/pay/unifiedorder');
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
          curl_setopt($ch, CURLOPT_POST, 1);
          curl_setopt($ch, CURLOPT_POSTFIELDS, $signParams);
          $output = curl_exec($ch);


          if (false === $output) {
            echo 'CURL Error:' . curl_error($ch);
            exit;
          }
          
          // 下单成功的话，微信返回个XML，里面包含prepayID，提取出来
          
          if (0 === preg_match('/<prepay_id><\!\[CDATA\[(\w+)\]\]><\/prepay_id>/', $output, $match)) {
            echo $output;
            exit(0);
          }

          $prepayId = $match[1];

          $response= [
            'appId' => \Wechat::APPID,
            // 随机串，32个字符以内
            'nonceStr' => (string) mt_rand(10000, 99999),
            // 微信规定
            'package' => 'prepay_id=' . $prepayId,
            // 加密形式
            'signType' => 'MD5',
            // 时间戳，注意得是字符串形式的
            'timeStamp' => (string) time(),
          ];
          $sequence = '';
          foreach ($response as $key => $value) {
            $sequence .= "$key=$value&";
          }

          $secretKey = \Wechat::MCH_KEY;

          $response['paySign'] = strtoupper(md5("{$sequence}key=$secretKey"));
          $response['code']    = \OrderConst::API_ORDER_STATUS['success'];
          return $response;

    }

    // 微信回调
    public function afterPayment($postXml) {
	    $attr = json_decode($postXml, true);
	    $notifyData = [
            'totalFee' => $attr['total_fee'],
            'openid'   => $attr['openid'],
            'orderId'  => $attr['out_trade_no'],
            'time'     => $attr['time_end']
        ];
        if ($notifyData['orderId']) {
            $orderInfo = Order::getItemById($notifyData['orderId']);
            if ($orderInfo) {
                $now = time();
                $orderInfo->payTime = $now;
                $orderInfo->isPay   = 1;
                $orderInfo->updateTime = $now;
                $orderInfo->status  = \OrderConst::ORDER_STATUS['finish'];
                if ($orderInfo->save()) {
                    $thirdService = new ThirdService;
                    $thirdPay     = $thirdService->peyOrder($orderInfo);
                    return true;
                }
            }
            return false;
        }
        return false;
    } 


    // 微信退款
    public function wechatRefound() {

        $orderId   = $this->_orderId;

        $orderInfo = Order::getItemByOrderId($orderId);

        if ($orderInfo) {

            $orderId      = $orderInfo->id;

            $nonce_str    = 'refind'.time().mt_rand(10000, 99999);

            $money        = $orderInfo->totalPrice * 100;

            $params = [
                'appid'  => \Wechat::APPID,

                'mch_id' => \Wechat::MCH_ID,
                // 随机串，32字符以内
                'nonce_str' => (string) $nonce_str, 
                // 订单金额     单位 转为分
                'total_fee' =>  $money,        
                // 退款金额 单位 转为分
                'refund_fee' => $money,        
                // 签名类型 支持HMAC-SHA256和MD5，默认为MD5
                'sign_type' => 'MD5',                   
                // 商户订单号
                'out_trade_no'   => $this->_orderId,    
                // 商户退款单号
                'out_refund_no'  => 'refind'.$this->_orderId,       
                // 退款原因
                'refund_desc'    => '申请退款',       
            ];

            $params['sign'] = $this->getRefindSign($params);

            $postXml      = $this->arrayToXml($params);

            $responseXml  = $this->curlPost($postXml);

            $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
            if ($unifiedOrder === false) {
                die('parse xml error');
            }
            if ($unifiedOrder->return_code != 'SUCCESS') {
                die($unifiedOrder->return_msg);
            }
            if ($unifiedOrder->result_code != 'SUCCESS') {
                die($unifiedOrder->err_code);
            }

            $orderInfo->status     =  \OrderConst::ORDER_STATUS['refind'];
            $orderInfo->updateTime = time();
            $orderInfo->isRefound  = 1;
            return $orderInfo->save();
        
        }

        return false;

    }

    private function curlPost($postData, $options = [] ) {

        $url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';

        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数

        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/cert/apiclient_cert.pem');
 
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY,getcwd().'/cert/apiclient_key.pem');

        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    // 生成付款签名
    private function makeSignParams($params) {
        ksort($params);
        $sequence = '';
        foreach ($params as $key => $value) {
          $sequence .= "$key=$value&";
        }
        $sequence = $sequence . "key=".\Wechat::MCH_KEY;
        $params['sign'] = strtoupper(md5($sequence));
        
        $xml = '<xml>' . PHP_EOL;
        foreach ($params as $key => $value) {
            $xml .= "<$key>$value</$key>" . PHP_EOL;
        }
        $xml .= '</xml>';
        return $xml;
    }

    // 申请退款签名
    private function getRefindSign($params)
    {
        $key = \Wechat::MCH_KEY;
        ksort($params, SORT_STRING);
        $unSignParaString = $this->formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    private function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }












}
